# auto load
extends Node


const _ITEM_INFOS_DIR: String = "res://data/item_infos/"
var _item_infos_dict: Dictionary[int, ItemInfo]
#var _prop_ivts: Dictionary[ItemInfo.Category, Inventory]
var consumable_props_ivt := Inventory.new()
var common_props_ivt := Inventory.new()
var skill_props_ivt := Inventory.new()
var weapon_props_ivt := Inventory.new()
var weapon_ivt := Inventory.new()


signal had_inventory_update(ivts: Array)


func _ready() -> void:
    _load_item_infos()
    _init_ivts()


func _init_ivts() -> void:
    consumable_props_ivt.list.resize(2)
    common_props_ivt.list.resize(999)
    skill_props_ivt.list.resize(3)
    weapon_props_ivt.list.resize(6)
    weapon_ivt.list.resize(3)


## 从指定的文件夹中加载物品信息
func _load_item_infos() -> void:
    var dir := DirAccess.open(_ITEM_INFOS_DIR)
    if not dir:
        printerr("无法打开该文件夹: ", _ITEM_INFOS_DIR)
        return
    
    for file in dir.get_files():
        var info := ResourceLoader.load(_ITEM_INFOS_DIR + file) as ItemInfo
        _item_infos_dict[info.id] = info
    

func get_item_info(id: int) -> ItemInfo:
    return _item_infos_dict.get(id)


func swap_item(ivt1: Inventory, idx1: int, ivt2: Inventory, idx2: int) -> void:
    var temp := ivt1.list[idx1]
    ivt1.list[idx1] = ivt2.list[idx2]
    ivt2.list[idx2] = temp
    
    had_inventory_update.emit([ivt1, ivt2])


## 向指定的仓库中添加指定数量的物品，返回添加后剩余的物品数量, 返回-1代表没有要添加的物品
func add_item(ivt: Inventory, id: int, count: int = 1) -> int:
    if count <= 0: return 0
    var info: ItemInfo = _item_infos_dict.get(id)
    if info == null: return -1
    # 物品不可堆叠
    if info.max_stack_count == 1:
        for i in range(ivt.list.size()):
            if count <= 0: break
            if ivt.list[i] != null: continue
            var slot := InventorySlot.new()
            slot.setup(id, 1)
            ivt.list[i] = slot
            count -= 1
    # 物品可堆叠
    elif info.max_stack_count > 1:
        # 在库存查找已存在的要添加的物品，并修改数量
        for i in range(ivt.list.size()):
            if count <= 0: break
            if ivt.list[i] == null or ivt.list[i].item_id != id: continue
            var c := count + ivt.list[i].item_count
            if c <= info.max_stack_count:
                ivt.list[i].item_count = c
                count = 0
                break
            ivt.list[i].item_count = info.max_stack_count
            count = c - info.max_stack_count

        # 库存中已有的要添加的物品都被遍历操作后，要添加的物品仍没被添加完，就查找库存中的空闲位置，在其上添加
        if count > 0:
            for i in range(ivt.list.size()):
                if count <= 0: break
                if ivt.list[i] != null: continue
                if count <= info.max_stack_count:
                    var slot := InventorySlot.new()
                    slot.setup(id, count)
                    ivt.list[i] = slot
                    count = 0
                    break
                else:
                    var slot := InventorySlot.new()
                    slot.setup(id, info.max_stack_count)
                    ivt.list[i] = slot
                    count -= info.max_stack_count

    had_inventory_update.emit([ivt])
    return count


## 向仓库中指定的位置添加指定数量的物品。返回添加后剩余的物品数量, 返回-1代表没有要添加的物品
func add_item_by_index(ivt: Inventory, id: int, count: int, index: int) -> int:
    if count <= 0: return 0
    var info: ItemInfo = _item_infos_dict.get(id)
    if not info: return -1

    # index 位置上没有物品
    if ivt.list[index] == null:
        var slot := InventorySlot.new()
        slot.item_id = id
        if info.max_stacked_count <= count:
            slot.item_count = info.max_stacked_count
            count -= info.max_stacked_count
        else:
            slot.item_count = count
            count = 0
    # index 位置上有物品
    else:
        # 同一种物品
        if id == ivt.list[index].item_id:
            if info.max_stacked_count > 1:
                var c = count + ivt.list[index].item_count
                if c <= info.max_stacked_count:
                    ivt.list[index].item_count = c
                    count = 0
                else:
                    ivt.list[index].item_count = info.max_stacked_count
                    count = c - info.max_stacked_count

    had_inventory_update.emit([ivt])
    return count


## 从仓库中删除指定位置上指定数量的物品
func remove_item_by_index(ivt: Inventory, index: int, count: int = 1) -> void:
    if count <= 0: return
    if ivt.list[index] == null: return
    var slot := ivt.list[index]
    slot.item_count -= count
    if slot.item_count <= 0:
        ivt.list[index] = null

    had_inventory_update.emit([ivt])


## 从仓库中删除指定数量的物品
func remove_item_by_id(ivt: Inventory, id: int, count: int = 1) -> void:
    if count <= 0: return
    var info: ItemInfo = _item_infos_dict.get(id)
    if info == null: return

    for i in range(ivt.list.size()):
        if count <= 0: break
        if ivt.list[i] == null or ivt.list[i].item_id != id: continue
        # 物品不可堆叠
        if info.max_stacked_count == 1:
            ivt.list[i] = null
            count -= 1
        # 物品可堆叠
        else:
            if ivt.list[i].item_count <= count:
                count -= ivt.list[i].item_count
                ivt.list[i] = null
            else:
                ivt.list[i].item_count -= count
                count = 0

    had_inventory_update.emit([ivt])


## 整理仓库，将库存中的物品重新依次存放 (按ID从小到大)
func organize_inventory(ivt: Inventory) -> void:
    ivt.list.sort_custom(
        func(a: InventorySlot, b: InventorySlot):
            if a and b and a.item_id < b.item_id:
                return true
            elif a and not b:
                return b
            else:
                return false
    )

    had_inventory_update.emit([ivt])


## 清空仓库
func clear_inventory(ivt: Inventory) -> void:
    ivt.list.fill(null)
    had_inventory_update.emit([ivt])
